#include <cassert>
#include <cstdio>
#include <iostream>
#include <memory>
#include <string>
#include "myast.h"
#include <fstream>
#include "koopa.h"
#include <unordered_map>
#include <map>

using namespace std;

// 声明 lexer 的输入, 以及 parser 函数
// 为什么不引用 sysy.tab.hpp 呢? 因为首先里面没有 yyin 的定义
// 其次, 因为这个文件不是我们自己写的, 而是被 Bison 生成出来的
// 你的代码编辑器/IDE 很可能找不到这个文件, 然后会给你报错 (虽然编译不会出错)
// 看起来会很烦人, 于是干脆采用这种看起来 dirty 但实际很有效的手段
extern FILE *yyin;
extern int yyparse(unique_ptr<BaseAST> &ast);
string koopa_str = "", riscv_str = "";
extern void gen_riscv();
extern unordered_map<BaseAST*, int> bbs_begin;
extern unordered_map<int, int> bbs_end;

int main(int argc, const char *argv[]) {
  // 解析命令行参数. 测试脚本/评测平台要求你的编译器能接收如下参数:
  // compiler 模式 输入文件 -o 输出文件
  assert(argc == 5);
  auto mode = argv[1];
  auto input = argv[2];
  auto output = argv[4];

  // 打开输入文件, 并且指定 lexer 在解析的时候读取这个文件
  yyin = fopen(input, "r");
  assert(yyin);

  // 调用 parser 函数, parser 函数会进一步调用 lexer 解析输入文件的
  unique_ptr<BaseAST> ast;
  auto ret = yyparse(ast);
  assert(!ret);

  // dump AST
  // ast->Dump();
  // cout << endl;
  // return 0;

  // gen koopa
  ast->Koo();
  // cout<< "bbs_begin:" << endl;
  // for(auto p = bbs_begin.begin(); p != bbs_begin.end(); p++)
  //   cout << p->second << " ";
  // cout << "bbs_end:" << endl;
  // for(auto p = bbs_end.begin(); p != bbs_end.end(); p++)
  //   cout << p->first << " " << p->second << endl;

  if(mode[1] == 'k'){
    // dump koopa
    fstream koopa_file;
    koopa_file.open(output, ios::out | ios::binary);
    koopa_file << koopa_str;
    koopa_file.close();
  }
  else{
    // gen riscv
    gen_riscv();
    // dump riscv
    fstream riscv_file;
    riscv_file.open(output, ios::out | ios::binary);
    riscv_file << riscv_str;
    riscv_file.close();
  }

  return 0;
}
